<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="824.48">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
p.p4 {margin: 0.0px 0.0px 0.0px 27.2px; text-indent: -0.2px; font: 12.0px Helvetica}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #bf0000}
p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #606060}
span.s1 {color: #0000ff}
span.s2 {color: #0000bf}
span.s3 {color: #000000}
span.s4 {color: #606060}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1"><b>Cepstrum<span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>Quefrency analysis and liftering</b></p>
<p class="p2"><br></p>
<p class="p3">Fourier analysis of the shape of a signal's log-power spectrum. Because this transform applies to magnitudes and not the phases (i.e. it ignores half of the data), <b><i>the cepstral Buffer is half the size of the FFT Buffer</i></b>.</p>
<p class="p2"><br></p>
<p class="p3">Forward transform (from spectral domain to cepstral domain):</p>
<p class="p3"><b>Cepstrum(cepbuf, fftchain)</b><span class="Apple-converted-space"> </span></p>
<p class="p4"><b>cepbuf</b> - a <a href="SC://Buffer"><span class="s1">Buffer</span></a> of half the size as the original FFT Buffer.</p>
<p class="p4"><b>fftchain</b> - a standard FFT chain as produced by the <a href="SC://FFT"><span class="s1">FFT</span></a> UGen or various PV_ UGens.</p>
<p class="p4">The output is a cepstral "chain" which can be treated in many regards like an FFT chain: you can apply PV_ transforms, for example.</p>
<p class="p2"><span class="Apple-tab-span">	</span></p>
<p class="p3">"Reverse" transform (from cepstral domain back to spectral domain):</p>
<p class="p3"><b>ICepstrum(cepchain, fftbuf)</b></p>
<p class="p4"><b>cepchain</b> - a cepstral chain, such as that produced by Cepstrum or any PV_ UGens that have operated on a cepstrum.</p>
<p class="p4"><b>fftbuf</b> - The FFT buffer, typically the one that was the original source used for the forward transform.</p>
<p class="p4">The output is a standard FFT chain.</p>
<p class="p2"><br></p>
<p class="p3">Very loosely speaking the cepstrum is an "FFT of an FFT". There are various forms of cepstral analysis - this UGen applies what is sometimes called the "power cepstrum": a Fourier analysis of the spectral log-magnitudes. (The log is important because that's part of what helps separate source-and-filter components in this procedure.) The reverse, ICepstrum, performs IFFT and exponentiates the result, to derive new magnitudes to be stored back into the <b>fftbuf</b> (phases are left untouched; they are essentially meaningless).</p>
<p class="p2"><br></p>
<p class="p3">See also: <a href="SC://MFCC"><span class="s1">MFCC</span></a>, <a href="SC://FFT"><span class="s1">FFT</span></a></p>
<p class="p2"><br></p>
<p class="p3"><b>Example</b></p>
<p class="p2"><br></p>
<p class="p5">s.boot;</p>
<p class="p6"><br></p>
<p class="p5">~fftbuf = <span class="s2">Buffer</span>.alloc(s, 2048);</p>
<p class="p5">~cepbuf = <span class="s2">Buffer</span>.alloc(s, 1024);</p>
<p class="p6"><br></p>
<p class="p5">(</p>
<p class="p5">x = {</p>
<p class="p5"><span class="Apple-tab-span">	</span><span class="s2">var</span> son, chain, cepsch;</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>// You might like to try uncommenting these different source signals:</p>
<p class="p5"><span class="Apple-tab-span">	</span>son = <span class="s2">WhiteNoise</span>.ar;</p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>//son = Impulse.ar(150);</p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>//son = SinOsc.ar(440);</p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>//son = SinOsc.ar([150, 1450, 7203, 12010]).mean;</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>// Or these filters:</p>
<p class="p5"><span class="Apple-tab-span">	</span>son = <span class="s2">MoogFF</span>.ar(son, 5350) * 5;</p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>//son = son + DelayN.ar(son, 0.003, 0.003);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p5"><span class="Apple-tab-span">	</span>chain = <span class="s2">FFT</span>(~fftbuf, son, wintype: 1);</p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span></p>
<p class="p5"><span class="Apple-tab-span">	</span>cepsch = <span class="s2">Cepstrum</span>(~cepbuf, chain);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>// PV_BrickWall can act as a low-pass filter, or here, as a wol-pass lifter...</p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>// ...in practical terms, produces a smoothed version of the spectrum</p>
<p class="p5"><span class="Apple-tab-span">	</span>cepsch = <span class="s2">PV_BrickWall</span>(cepsch, -0.95);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p5"><span class="Apple-tab-span">	</span><span class="s2">ICepstrum</span>(cepsch, ~fftbuf);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p7"><span class="s3"><span class="Apple-tab-span">	</span></span>// We'll stop the unit after 1 second, the results are visible quickly enough</p>
<p class="p5"><span class="Apple-tab-span">	</span><span class="s2">Line</span>.kr(1,0,1, doneAction: 2);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p5"><span class="Apple-tab-span">	</span>son * 0.1</p>
<p class="p5">}.play;</p>
<p class="p5">)</p>
<p class="p6"><br></p>
<p class="p7">// A convenience function to plot magnitudes:</p>
<p class="p5">~plotmags = {<span class="s2">|buf, lbl|</span> buf.loadToFloatArray(action:{<span class="s2">|data|</span> {data[0,2..]<span class="Apple-converted-space">  </span>.max(0.000001)<span class="Apple-converted-space">  </span>.log.normalize<span class="Apple-converted-space">  </span>.plot(lbl)}.defer})};</p>
<p class="p6"><br></p>
<p class="p5">~plotmags.(~cepbuf, <span class="s4">"cepstrum"</span>);</p>
<p class="p8"><span class="s3">~plotmags.(~fftbuf, </span>"liftered (smoothed) spectrum"<span class="s3">);</span></p>
<p class="p6"><br></p>
<p class="p5">[~fftbuf, ~cepbuf].do(<span class="s2">_</span>.free);</p>
<p class="p2"><br></p>
<p class="p3">In the above example, the cepstrum plot itself may be difficult to interpret (although you can clearly see what the PV_BrickWall unit has done), but the liftered spectrum should look reasonably smooth and show the main peaks and troughs of the spectrum (try running the example without ICepstrum to see the unsmoothed version).</p>
<p class="p2"><br></p>
<p class="p3">Note: the cepstral analysis here includes the DC bin and ignores the Nyquist bin, so as to ensure that the resulting number of bins is a power of two.</p>
</body>
</html>
